/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	RBRemoteServiceServlet.java
 * 模块说明：	
 * 修改历史：
 * Nov 29, 2007 - lxm - 创建。
 */
package com.hd123.rumba.gwt.base.server;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.hibernate.HibernateException;

import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.hd123.rumba.action.ViewApplication;
import com.hd123.rumba.domain.IDomain;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.gwt.base.client.RBRemoteService;
import com.hd123.rumba.gwt.base.client.Session;
import com.hd123.rumba.gwt.base.client.biz.BSimpleBasic;
import com.hd123.rumba.gwt.base.client.biz.SDomain;
import com.hd123.rumba.gwt.base.client.exception.ClientBizException;
import com.hd123.rumba.gwt.base.server.biz.SDomainReader;
import com.hd123.rumba.gwt.organization.client.biz.SOrganization;
import com.hd123.rumba.gwt.organization.server.biz.SOrganizationReader;
import com.hd123.rumba.gwt.user.client.biz.SUser;
import com.hd123.rumba.gwt.user.server.biz.SUserReader;
import com.hd123.rumba.log.RumbaLogger;
import com.hd123.rumba.organization.IOrganization;
import com.hd123.rumba.request.Action;
import com.hd123.rumba.request.Dictionary;
import com.hd123.rumba.runtime.HibernateSession;
import com.hd123.rumba.user.IUser;
import com.hd123.rumba.util.ObjectUtil;

/**
 * @author lxm
 * 
 */
public class RBRemoteServiceServlet extends RemoteServiceServlet implements RBRemoteService {

  protected RumbaLogger logger = RumbaLogger.getLogger(this.getClass());

  public Session getCurrentSession(HashMap params) throws ClientBizException {
    Session session = new Session();
    session.setUser(this.getCurrentUser());
    session.setDomain(this.getCurrentDomain());
    session.setOrganization(this.getCurrentOrganization());
    return session;
  }

  public void login(String loginName, String password, String tokenValue, String domainCode)
      throws ClientBizException {
    try {
      Dictionary dd = new Dictionary(getRequest().getSession());
      dd.putFormValue("start", "processLogin");
      dd.putFormValue("LoginForm_Login", loginName);
      dd.putFormValue("LoginForm_Password", password);
      dd.putFormValue("LoginForm_Token", tokenValue);
      dd.putFormValue("LoginForm_RegistrationDomain", domainCode);
      Action action = new ViewApplication();
      action.init(dd);
      action.execute();
      if (dd.getErrorText() != null)
        throw new ClientBizException(dd.getErrorText());
    } catch (Exception e) {
      throw new ClientBizException("登录过程中发生错误:[" + e + "]" + e.getMessage());
    }
  }

  public void logout() {
    getRequest().getSession().invalidate();
  }

  /**
   * 重写此方法，以确保HibernateSession.closeSession()总能被调用。
   */
  public String processCall(String payload) throws SerializationException {
    try {
      return super.processCall(payload);
    } finally {
      try {
        HibernateSession.closeSession();
      } catch (HibernateException e) {
      }
    }
  }

  private HttpServletRequest request;
  private HttpServletResponse response;

  public HttpServletRequest getRequest() {
    return request != null ? request : this.getThreadLocalRequest();
  }

  public void setRequest(HttpServletRequest request) {
    this.request = request;
  }

  public HttpServletResponse getResponse() {
    return response;
  }

  public void setResponse(HttpServletResponse response) {
    this.response = response;
  }

  protected Object getSessionValue(String key) throws ClientBizException {
    Object value = getSessionValues().get(key);
    if (value == null) {
      ensureLogin();
      value = getSessionValues().get(key);
      if (value == null)
        throw new ClientBizException("尚未登录");
    }
    return value;
  }

  protected Hashtable getSessionValues() {
    Hashtable h = (Hashtable) getRequest().getSession().getAttribute(Dictionary.SESSIONMARKER);
    if (h == null) {
      h = new Hashtable();
      getRequest().getSession().setAttribute(Dictionary.SESSIONMARKER, h);
    }
    return h;
  }

  protected void setSessionValue(String key, Object value) {
    getSessionValues().put(key, value);
  }

  /**
   * 统一的异常报告处理。
   * 
   * @param message
   * @param e
   */
  protected void reportError(Object message, Throwable t) {
    RumbaLogger.getLogger(this.getClass()).error(message, t);
  }

  /**
   * Service标准异常处理。设计用于Service最外层调用。<br>
   * 将自动产生错误信息到日志，并将消息以ClientBizException的方式将异常信息返回给客户端。
   * 
   * @param message
   * @param t
   * @return ClientBizException
   */
  protected ClientBizException buildException(Object message, Throwable t) {
    reportError(message, t);
    String msg = message != null ? message + "\n" : "";
    msg += t.getMessage();
    return new ClientBizException(msg);
  }

  private void ensureLogin() throws ClientBizException {
    try {
      InputStream is = getClass().getResourceAsStream("/debug-login.properties");
      Properties props = new Properties();
      props.load(is);
      login(props.getProperty("login"), props.getProperty("password"), null, props
          .getProperty("domain"));
      logger.warn("从/debug-login.properties中读取登录信息: " + props.getProperty("login") + "@"
          + props.getProperty("domain"));
    } catch (Exception e) {
    }
  }

  private BSimpleBasic currentUser = null;
  private BSimpleBasic currentDomain = null;
  private BSimpleBasic currentOrganization = null;

  private BSimpleBasic getCurrentUser() throws ClientBizException {
    IUser puser = this.getCurrentUserPerz();
    if (puser == null) {
      currentUser = null;
      return currentUser;
    }
    SUserReader reader = new SUserReader();
    try {
      if (currentUser == null || !currentUser.getUuid().equals(puser.getUuid())) {
        SUser suser = new SUser();
        reader.setTarget(suser);
        reader.read(puser);
        currentUser = suser.toSimple();
      }
    } catch (ClientBizException e) {
      ClientBizException se = new ClientBizException();
      se.initCause(e);
      throw se;
    } catch (BusinessException e) {
      ClientBizException se = new ClientBizException();
      se.initCause(e);
      throw se;
    }
    return currentUser;
  }

  protected IUser getCurrentUserPerz() throws ClientBizException {
    return (IUser) this.getSessionValue(Dictionary.CURRENTUSER);
  }

  private BSimpleBasic getCurrentDomain() throws ClientBizException {
    IDomain pdomain = this.getCurrentDomainPerz();
    if (pdomain == null) {
      currentDomain = null;
      return currentDomain;
    }
    SDomainReader reader = new SDomainReader();
    try {
      if (currentDomain == null || !currentDomain.getUuid().equals(pdomain.getUuid())) {
        SDomain sdomain = new SDomain();
        reader.setTarget(sdomain);
        reader.read(pdomain);
        currentDomain = sdomain.toSimple();
      }
    } catch (ClientBizException e) {
      ClientBizException se = new ClientBizException();
      se.initCause(e);
      throw se;
    } catch (BusinessException e) {
      ClientBizException se = new ClientBizException();
      se.initCause(e);
      throw se;
    }
    return currentDomain;
  }

  protected IDomain getCurrentDomainPerz() throws ClientBizException {
    return (IDomain) this.getSessionValue(Dictionary.CURRENTDOMAIN);
  }

  private BSimpleBasic getCurrentOrganization() throws ClientBizException {
    IOrganization porg = this.getCurrentOrganizationPerz();
    if (porg == null) {
      currentOrganization = null;
      return currentOrganization;
    }
    SOrganizationReader reader = new SOrganizationReader();
    try {
      if (currentOrganization == null || !currentOrganization.getUuid().equals(porg.getUuid())) {
        SOrganization sorg = new SOrganization();
        reader.setTarget(sorg);
        reader.read(porg);
        currentOrganization = sorg.toSimple();
      }
    } catch (BusinessException e) {
      ClientBizException se = new ClientBizException();
      se.initCause(e);
      throw se;
    } catch (ClientBizException e) {
      ClientBizException se = new ClientBizException();
      se.initCause(e);
      throw se;
    }
    return currentOrganization;
  }

  protected IOrganization getCurrentOrganizationPerz() throws ClientBizException {
    return (IOrganization) this.getSessionValues().get(Dictionary.CURRENTORGANIZATION);
  }

  
  /**
   * 检查当前登录用户是否拥有指定的权限。
   * 
   * @param permCode
   *          指定权限代码。允许null，将返回false。
   * @throws BusinessException
   * @throws ClientBizException 
   */
  protected void checkPermission(String permCode) throws BusinessException, ClientBizException {
    ObjectUtil.assertion(getCurrentUserPerz().hasPermission(permCode), BusinessException
        .noPermission(permCode));
  }
}
